package org.popupcommunication.model;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.PostPersist;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;

//@NamedQuery(name = "findUserByEmail", query = " from users where email=:email")

@Entity
@Table(name = "users")
public class User implements Comparable<User>, Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int idUser;

	@NotNull
	@Size(min = 1, max = 100)
	@Column(nullable = false, length = 100)
	private String firstName;

	@NotNull
	@Size(min = 1, max = 100)
	@Column(nullable = false, length = 100)
	private String lastName;

	@Column(nullable = false, length = 20)
	private String password;

	@NotNull
	@Size(min = 1, max = 100)
	@Email
	@Column(nullable = false, length = 100, unique = true)
	private String email;

	@Size(min = 0, max = 100)
	@Column(length = 100)
	private String fonction;

	@Size(min = 0, max = 100)
	@Column(length = 100)
	private String institution;

	@Size(min = 0, max = 20)
	@Column(length = 20)
	private String tel;

	@Size(min = 0, max = 20)
	@Column(length = 20)
	private String gsm;

	private boolean isAdmin;

	private boolean isActivate;

	private Date dateLastBadAttempt;

	private int errorConnection;

	private Date dateReactivate;

	private String srcAvatar;

	private String codeVerif;

	private Date dateLimitCode;

	private Date dateLastConnexion;

	private Date dateRegister;

	@Basic(fetch = FetchType.EAGER)
	@ManyToMany(cascade = CascadeType.ALL)
	private Set<Group> listGroup = new HashSet<Group>();

	@OneToMany(mappedBy = "createur", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
	private Set<SujetForum> listSujets;	
	
	@OneToMany(mappedBy = "postedBy")
	private Set<ResponseForum> listReponses;			

	public Set<ResponseForum> getListReponses() {
		return listReponses;
	}

	public void setListReponses(Set<ResponseForum> rep) {
		this.listReponses = rep;
	}
	
	public void addReponse(ResponseForum r) {
		this.listReponses.add(r);
	}	
	public Set<SujetForum> getListSujets() {
		return listSujets;
	}

	public void setListSujets(Set<SujetForum> sujets) {
		this.listSujets = sujets;
	}
	
	public void addSujet(SujetForum s) {
		this.listSujets.add(s);
	}
	public Set<Group> getListGroup() {
		return listGroup;
	}

	public void setListGroup(Set<Group> listGroup) {
		this.listGroup = listGroup;
	}

	public void addGroup(Group g) {
		this.listGroup.add(g);
	}

	transient @Transient
	boolean isBeingPersisted = false;

	public User() {
	}

	public User(String fn, String ln, String e, String pwd, String fonct,
			String instit, String tel, String gsm, boolean adm) {
		this.firstName = fn;
		this.lastName = ln;
		this.email = e;
		this.password = pwd;
		this.fonction = fonct;
		this.institution = instit;
		this.tel = tel;
		this.gsm = gsm;
		this.isAdmin = adm;
	}

	public int getIdUser() {
		return idUser;
	}

	public void setIdUser(int idUser) {
		this.idUser = idUser;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getFonction() {
		return fonction;
	}

	public void setFonction(String fonction) {
		this.fonction = fonction;
	}

	public String getInstitution() {
		return institution;
	}

	public void setInstitution(String institution) {
		this.institution = institution;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public String getGsm() {
		return gsm;
	}

	public void setGsm(String gsm) {
		this.gsm = gsm;
	}

	public boolean isActivate() {
		return isActivate;
	}

	public void setActivate(boolean isActivate) {
		this.isActivate = isActivate;
	}

	public Date getDateLastBadAttempt() {
		return dateLastBadAttempt;
	}

	public void setDateLastBadAttempt(Date dateLastBadAttempt) {
		this.dateLastBadAttempt = dateLastBadAttempt;
	}

	public int getErrorConnection() {
		return errorConnection;
	}

	public void setErrorConnection(int errorConnection) {
		this.errorConnection = errorConnection;
	}

	public Date getDateReactivate() {
		return dateReactivate;
	}

	public void setDateReactivate(Date dateReactivate) {
		this.dateReactivate = dateReactivate;
	}

	public String getSrcAvatar() {
		return srcAvatar;
	}

	public void setSrcAvatar(String srcAvatar) {
		this.srcAvatar = srcAvatar;
	}

	public String getCodeVerif() {
		return codeVerif;
	}

	public void setCodeVerif(String codeVerif) {
		this.codeVerif = codeVerif;
	}

	public Date getDateLimitCode() {
		return dateLimitCode;
	}

	public void setDateLimitCode(Date dateLimitCode) {
		this.dateLimitCode = dateLimitCode;
	}

	public Date getDateLastConnexion() {
		return dateLastConnexion;
	}

	public void setDateLastConnexion(Date dateLastConnexion) {
		this.dateLastConnexion = dateLastConnexion;
	}

	public Date getDateRegister() {
		return dateRegister;
	}

	public void setDateRegister(Date dateRegister) {
		this.dateRegister = dateRegister;
	}

	public boolean isAdmin() {
		return isAdmin;
	}

	public void setAdmin(boolean isAdmin) {
		this.isAdmin = isAdmin;
	}

	public boolean getIsAdmin() {
		return isAdmin;
	}

	public void setIsAdmin(boolean isAdmin) {
		this.isAdmin = isAdmin;
	}

	public int getNbGroup(){
		return listGroup.size();
	}
	public boolean onlyOneGroup(){
		return (this.getNbGroup()==1)?true:false;
	}
	public Group getSingleGroup(){
		if (onlyOneGroup()){
	    Iterator<Group> it = listGroup.iterator();
	    while(it.hasNext())
	      return it.next();	    
		}
		return null;
	}
	


	@Override
	public String toString() {
		return String.valueOf(idUser);
	}

	@Override
	public int compareTo(User o) {
		if (lastName.compareTo(o.getLastName()) != 0) {
			return lastName.compareTo(o.getLastName());
		}
		return firstName.compareTo(o.getFirstName());
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) {
			return true;
		}

		if (o == null) {
			return false;
		}

		if (getClass() != o.getClass()) {
			return false;
		}

		User other = (User) o;

		return email.equals(other.email);
	}

	@Override
	public int hashCode() {
		if (getEmail() != null) {
			return this.getEmail().hashCode();
		} else if (isBeingPersisted) {/*
									 * Prevents errors during Hibernate
									 * validation. Hibernate calls HashCode()
									 * for no reason during em.persist() while
									 * doing the validation, causing problems
									 * when entities are created.
									 */
			return 0; // I guess that Hibernate validation does not really use
						// that value anyway. It's a hack.
		} else { // No id yet and not being persisted.

			return 0;
		}
	}

	@PrePersist
	public void prePersist() {
		isBeingPersisted = true;
	}

	@PostPersist
	public void postPersist() {
		isBeingPersisted = false;
	}

}
